import threading
from PyQt5.QtCore import pyqtSignal, QObject

from zlgcan.zlgcan import *


class CANController(QObject):
    data_received = pyqtSignal(int, str, int, int, int, str)
    def __init__(self, window):
        super().__init__()
        self.zcanlib = ZCAN()
        self.device_handle = None
        self.chn_handle = None
        self.rcv_thread = None
        self.running = False
        self.window = window  # 保存窗口实例
        self.data_received.connect(self.window.update_table)  # 连接信号到窗口方法
    def start(self):
        print("尝试打开 USBCAN-I 设备...")
        self.device_handle = self.zcanlib.OpenDevice(ZCAN_USBCAN1, 0, 0)
        if self.device_handle == INVALID_DEVICE_HANDLE:
            print("打开 USBCAN-I 设备失败！")
            return
        print("打开 USBCAN-I 设备成功！")
        self.chn_handle = self.can_I_start(0)
        self.running = True
        self.rcv_thread = threading.Thread(target=self.receive_data)
        self.rcv_thread.start()

    def can_I_start(self, chn):
        print(f"设置 CH{chn} 的波特率...")
        ret = self.zcanlib.ZCAN_SetValue(self.device_handle, str(chn) + "/baud_rate", "500000".encode("utf-8"))  # 500Kbps
        if ret != ZCAN_STATUS_OK:
            print(f"设置 CH{chn} 的波特率失败！")
            return
        print(f"CH{chn} 的波特率设置成功！")
        chn_init_cfg = ZCAN_CHANNEL_INIT_CONFIG()
        chn_init_cfg.can_type = ZCAN_TYPE_CAN
        chn_init_cfg.config.can.acc_code = 0
        chn_init_cfg.config.can.acc_mask = 0xFFFFFFFF
        chn_init_cfg.config.can.mode = 0
        chn_handle = self.zcanlib.InitCAN(self.device_handle, chn, chn_init_cfg)
        if chn_handle == 0:
            print(f"initCAN{chn} 失败！")
            return
        ret = self.zcanlib.StartCAN(chn_handle)
        if ret != ZCAN_STATUS_OK:
            print(f"startCAN{chn} 失败！")
            return
        return chn_handle

    def send_messages(self, transmit_num=10):
        if not self.running:
            print("设备尚未启动!")
            return
        msgs = (ZCAN_Transmit_Data * transmit_num)()
        for i in range(transmit_num):
            msgs[i].transmit_type = 2  # 0-正常发送，2-自发自收
            msgs[i].frame.eff = 0  # 0-标准帧，1-扩展帧
            msgs[i].frame.rtr = 0  # 0-数据帧，1-远程帧
            msgs[i].frame.can_id = i
            msgs[i].frame.can_dlc = 8
            for j in range(msgs[i].frame.can_dlc):
                msgs[i].frame.data[j] = j
        ret = self.zcanlib.Transmit(self.chn_handle, msgs, transmit_num)
        print(f"Transmit Num: {ret}.")

    def stop(self):
        if not self.running:
            print("设备尚未启动!")
            return
        self.running = False
        ret = self.zcanlib.ResetCAN(self.chn_handle)
        if ret == 1:
            print("ResetCAN 成功!")
        ret = self.zcanlib.CloseDevice(self.device_handle)
        if ret == 1:
            print("CloseDevice 成功!")
        if self.rcv_thread.is_alive():
            self.rcv_thread.join()

    def receive_data(self):
        while self.running:
            rcv_num = self.zcanlib.GetReceiveNum(self.chn_handle, ZCAN_TYPE_CAN)
            # rcv_canfd_num = self.zcanlib.GetReceiveNum(self.chn_handle, ZCAN_TYPE_CANFD)
            if rcv_num:
                rcv_msg, rcv_num = self.zcanlib.Receive(self.chn_handle, rcv_num)
                for i in range(rcv_num):
                    print(f"[{i}]: timestamps:{rcv_msg[i].timestamp}, type:CAN, id:{hex(rcv_msg[i].frame.can_id)}, "
                          f"dlc:{rcv_msg[i].frame.can_dlc}, eff:{rcv_msg[i].frame.eff}, rtr:{rcv_msg[i].frame.rtr}, "
                          f"data:{''.join(hex(rcv_msg[i].frame.data[j]) + ' ' for j in range(rcv_msg[i].frame.can_dlc))}")
                timestamp = rcv_msg[i].timestamp
                can_id = hex(rcv_msg[i].frame.can_id)
                dlc = rcv_msg[i].frame.can_dlc
                eff = rcv_msg[i].frame.eff
                rtr = rcv_msg[i].frame.rtr
                data = ''.join(hex(rcv_msg[i].frame.data[j]) + ' ' for j in range(dlc))
                # self.window.update_table(timestamp, can_id, dlc, eff, rtr, data)
                self.data_received.emit(timestamp, can_id, dlc, eff, rtr, data)  #
# # 使用示例
# if __name__ == '__main__':
#     can_controller = CANController()
#     can_controller.start()
#     can_controller.send_messages()
#     can_controller.stop()